/**
 *  Copyright (c) 2014 The xmlepf project.  All rights reserved.
 *
 *  This file is part of xmlepf (Event Driven Testing Framework).
 *
 *  xmlepf is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  xmlepf is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with xmlepf.  If not, see <http://www.gnu.org/licenses/>.
 *
 *  This software consists of voluntary contributions made by many
 *  individuals.  For exact contribution history, see the revision
 *  history and logs, available at http://code.google.com/p/xmlepf.
 */
package org.xmlepf.xtemp.script;

import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.xmlepf.xml.adapter.XPath;
import org.xmlepf.xml.adapter.NodeSerializer;
import org.xmlepf.utils.ObjectCreator;

/**
 *
 *
 */
public class ScriptPackage {

    private String name = "unknown";
    private Scriplet scriplet;
    private XPath xPath;
    private NodeSerializer s;
    private ExecutionContext executionContext;

    public ScriptPackage() throws Exception {
        scriplet = (Scriplet) ObjectCreator.get("Scriplet");
        executionContext = (ExecutionContext) ObjectCreator.get("ExecutionContext");
        xPath = (XPath) ObjectCreator.get("XPath");
        s = (NodeSerializer) ObjectCreator.get("NodeSerializer");
    }

    public void initialize( ExecutionContext executionContext ) throws Exception {
        this.executionContext = executionContext;
        
        xPath.initialize(executionContext.getScript());
        List<String> scriptPackages = s.serializeAsList(xPath.query("/script-package"));
        if (!scriptPackages.isEmpty()) {
            String executionContextXml = s.serialize(xPath.query("/script-package/execution-context"));
            executionContext.initialize(executionContextXml);
        }
    }

    public void run() {
        try {
            String xmlScriplet = null;
            if (executionContext.hasRealScripletThreading()) {
                // When running with "real scriplet threading" (i.e. one OS thread per scriplet),
                // each scriplet (<scriplet async="true">) will have its own XSLT 
                // instance. This means each async="true" scriplet is running independently (execution context wise)
                // from the other scriplets. But they can be synchronized/joined via events (on the event board, of course).
                // In this case any scriplet synchronization is possible, making "real-time" testing/monitoring scenarios possible.
                xmlScriplet = executionContext.getScripletWithName(executionContext.getStartWithScriplet());
            } else {
                // When running with "simulated scriplet threading" (i.e. one OS thread per script package),
                // each scriplet (<scriplet async="true">) will use the same "script package" wide
                // XSLT instance. This means each async="true" scriplet is running dependently (execution context wise)
                // from the other scriplets, exactly as specified in the XTemp draft.
                // In this case synchronization between differents scriplets using events is more limited (see XTemp draft)
                xmlScriplet = executionContext.getScript();
            }

            scriplet.setScriplet(xmlScriplet);
            scriplet.setTranslator(executionContext.getTranslator());
            scriplet.setExecutionContext(executionContext);
            scriplet.initialize();

            if (executionContext.hasRealScripletThreading()) {
                Thread scripletThread = new Thread(scriplet);
                scripletThread.start();
                scripletThread.join();
            } else {
                scriplet.run();
            }
        } catch (Exception ex) {
            Logger.getLogger(ScriptPackage.class.getName()).log(Level.SEVERE, ex.toString());
        }
    }

    public String getName() {
        return name;
    }

    public String getResult() {
        return scriplet.getResult();
    }
}
